import { isUndefined, isNull, PagedList, PageParams } from "mmb";
import * as brand_endorse_requestpb from "../grpc-client/service/brand_endorse_request_pb";
import { jsTimestampToPb, pbTimestampToJs } from "./helper";
import GrpcErrCode from "../grpc-client/grpcErrCode";
import AuditResult from "../bg-enums/auditResult";
import {
  getBgsBrandEndorseRequestOpSafely,
  getMetadata,
  getOptionsOfLight,
  wrapperGrpcError,
} from "../grpc-client/grpcAdapter";

import {
  BrandEndorseRequest,
  BrandEndorseRequestWithUserInfo,
  ApplyBrandEndorseRequestParams,
  AuditBrandEndorseRequestParams,
} from "./declareTypes";
/****************************************************************************************/
/*                                   brand_endorse_request entity                       */
/****************************************************************************************/

const brandEndorseRequestPbToObject = (
  pb: brand_endorse_requestpb.BrandEndorseRequestEntity
): BrandEndorseRequest => {
  return {
    brandEndorseRequestId: `${pb.getId()}`,
    brandId: `${pb.getBrandId()}`,
    userId: `${pb.getUserId()}`,
    requested: pbTimestampToJs(pb.getRequested())!,
    audited: pbTimestampToJs(pb.getAudited()),
    applyFields: pb.getApplyFields(),
    auditResult: pb.getAuditResult() as AuditResult,
  };
};

/****************************************************************************************/
/*                                   brand_endorse_request cmd                          */
/****************************************************************************************/

export const applyBrandEndorseRequest = async ({
  brandId,
  userId,
  applyFields,
}: ApplyBrandEndorseRequestParams): Promise<BrandEndorseRequest> => {
  const cl = getBgsBrandEndorseRequestOpSafely();
  const req = new brand_endorse_requestpb.ApplyBrandEndorseRequestRequest();

  req.setBrandId(Number(brandId));
  req.setUserId(Number(userId));
  req.setApplyFields(applyFields);

  return new Promise((resolve, reject) => {
    cl.applyBrandEndorseRequest(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(brandEndorseRequestPbToObject(res.getBrandEndorseRequest()!));
      }
    );
  });
};

export const auditBrandEndorseRequest = async ({
  brandEndorseRequestId,
  audited,
  auditResult,
}: AuditBrandEndorseRequestParams): Promise<BrandEndorseRequest> => {
  const cl = getBgsBrandEndorseRequestOpSafely();
  const req = new brand_endorse_requestpb.AuditBrandEndorseRequestRequest();

  req.setId(Number(brandEndorseRequestId));
  req.setAudited(jsTimestampToPb(audited));
  req.setAuditResult(auditResult);

  return new Promise((resolve, reject) => {
    cl.auditBrandEndorseRequest(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(brandEndorseRequestPbToObject(res.getBrandEndorseRequest()!));
      }
    );
  });
};

/****************************************************************************************/
/*                                   brand_endorse_request query                        */
/****************************************************************************************/

export const getBrandEndorseRequest = async (
  brandEndorseRequestId: string
): Promise<BrandEndorseRequest> => {
  const cl = getBgsBrandEndorseRequestOpSafely();
  const req = new brand_endorse_requestpb.GetBrandEndorseRequestRequest();

  req.setId(Number(brandEndorseRequestId));

  return new Promise((resolve, reject) => {
    cl.getBrandEndorseRequest(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(brandEndorseRequestPbToObject(res.getBrandEndorseRequest()!));
      }
    );
  });
};

export const getBrandEndorseRequestByBrandIDAndUserIDSafely = async (
  brandId,
  userId: string
): Promise<BrandEndorseRequest> => {
  const v = await getBrandEndorseRequestByBrandIDAndUserID(brandId, userId);
  return v!;
};

export const getBrandEndorseRequestByBrandIDAndUserID = async (
  brandId,
  userId: string
): Promise<BrandEndorseRequest | undefined> => {
  const cl = getBgsBrandEndorseRequestOpSafely();
  const req = new brand_endorse_requestpb.GetBrandEndorseRequestByBrandIDAndUserIDRequest();

  req.setBrandId(Number(brandId));
  req.setUserId(Number(userId));

  return new Promise((resolve, reject) => {
    cl.getBrandEndorseRequestByBrandIDAndUserID(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          if (opRet.getCode() === GrpcErrCode.NOT_FOUND) {
            resolve(undefined);
            return;
          } else {
            reject(wrapperGrpcError(opRet.getMsg()));
            return;
          }
        }
        resolve(brandEndorseRequestPbToObject(res.getBrandEndorseRequest()!));
      }
    );
  });
};

/****************************************************************************************/
/*                                   brand_endorse_requestJoins entity                  */
/****************************************************************************************/

const brandEndorseRequestWithUserInfoPbToObject = (
  pb: brand_endorse_requestpb.BrandEndorseRequestWithUserInfoEntity
): BrandEndorseRequestWithUserInfo => {
  return {
    brandEndorseRequestId: `${pb.getId()}`,
    brandId: `${pb.getBrandId()}`,
    userId: `${pb.getUserId()}`,
    requested: pbTimestampToJs(pb.getRequested())!,
    audited: pbTimestampToJs(pb.getAudited()),
    applyFields: pb.getApplyFields(),
    auditResult: pb.getAuditResult() as AuditResult,
    userPic: pb.getUserPic(),
  };
};

/****************************************************************************************/
/*                                   brand_endorse_requestJoins query                   */
/****************************************************************************************/

export const listBrandEndorseRequestWithUserInfosByBrandID = async (
  brandId: string,
  isWaitAudit: boolean,
  pager: PageParams
): Promise<PagedList<BrandEndorseRequest>> => {
  const cl = getBgsBrandEndorseRequestOpSafely();
  const req = new brand_endorse_requestpb.ListBrandEndorseRequestWithUserInfosByBrandIDRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setTs(jsTimestampToPb(pager.ts))
  req.setBrandId(Number(brandId));
  let auditResults = isWaitAudit ? [AuditResult.PENDING] : [AuditResult.APPROVED, AuditResult.REJECTED]
  req.setAuditResultsList(auditResults)

  return new Promise((resolve, reject) => {
    cl.listBrandEndorseRequestWithUserInfosByBrandID(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<BrandEndorseRequest> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res
          .getBrandEndorseRequestWithUserInfosList()
          .map(brandEndorseRequestWithUserInfoPbToObject);
        resolve(ret);
      }
    );
  });
};
